<script lang="ts" setup>
import {ref, reactive} from "vue";
import type {Editor, EditorConfiguration} from "codemirror";
import Codemirror from "codemirror-editor-vue3";
// mode代码高亮
import "codemirror/mode/javascript/javascript.js"

// 代码错误检查 (Lint)
import "codemirror/addon/lint/lint.js";
import "codemirror/addon/lint/json-lint.js"; // JSON 语法检查
import "codemirror/addon/lint/lint.css"; // Lint 样式

// 自动补全
import "codemirror/addon/hint/show-hint.js";
import "codemirror/addon/hint/show-hint.css";

// 括号匹配
import "codemirror/addon/edit/matchbrackets.js";

// 代码折叠
import "codemirror/addon/fold/foldcode.js";
import "codemirror/addon/fold/foldgutter.js";
import "codemirror/addon/fold/brace-fold.js";
import "codemirror/addon/fold/foldgutter.css";

import "codemirror/addon/edit/closebrackets.js"; // 自动补全括号 & 引号

// 需要全局提供 jsonlint
// @ts-ignore
import jsonlint from "jsonlint-mod";
import {useTestCaseStore} from "@/stores/test-case.ts";
// 在 script 标签顶部添加以下代码
declare global {
  interface Window {
    jsonlint: any;
  }
}
window.jsonlint = jsonlint;

const code = ref('');

const cmOptions: EditorConfiguration = reactive({
  mode: "application/json",
  theme: "default",
  readOnly: false,
  lineNumbers: true,
  lineWiseCopyCut: true,
  gutters: ["CodeMirror-lint-markers", "CodeMirror-foldgutter"], // ✅ 语法检查 & 代码折叠
  lint: true,// 语法检查
  matchBrackets: true,
  extraKeys: {
    "Ctrl-L": "autocomplete", // ✅ 代码自动补全
    "Ctrl-Q": (cm) => cm.foldCode(cm.getCursor()), // ✅ 折叠代码
    "Ctrl-Alt-L": () => formatJson(), // ✅ JSON 格式化
  },
  autoCloseBrackets: true,
});

// ✅ 手动格式化 JSON
const formatJson = () => {
  if (cminstance.value) {
    try {
      const currentCode = cminstance.value.getValue();
      const formattedCode = JSON.stringify(JSON.parse(currentCode), null, 2);
      cminstance.value.setValue(formattedCode);
    } catch (error) {
      console.error("JSON 格式错误，无法格式化:", error);
    }
  }
};

const testCaseStore = useTestCaseStore();

const cminstance = ref<Editor | null>(null);
const onReady = (cm: Editor) => {
  cminstance.value = cm;
  // console.log(cm.getValue());
};

function setCode(newCode: string) {
  code.value = newCode
  if (cminstance.value) {
    cminstance.value.setValue(newCode)
  }
}

defineExpose({
  code,
  setCode
})


</script>

<template>
  <Codemirror
      v-model:value="code"
      :options="cmOptions"
      height="100%"
      width="100%"
      class="cm-component"
      :border="true"
      @ready="onReady"
  />
</template>

<style lang="scss" scoped>
.cm-component {
  font-family: monospace;
}
</style>
